package cn.iocoder.yudao.module.pay.service.walletwithdraw;

import cn.iocoder.yudao.framework.common.enums.pay.PayWalletBizTypeEnum;
import cn.iocoder.yudao.framework.common.enums.pay.PayWalletTypeEnum;
import cn.iocoder.yudao.framework.common.enums.pay.WithdrawStatusEnum;
import cn.iocoder.yudao.framework.common.enums.pay.WithdrawTypeEnum;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.member.api.pickup.PickupInfoApi;
import cn.iocoder.yudao.module.member.api.pickup.PickupInfoDTO;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.pay.controller.admin.walletwithdraw.vo.PayWalletMetalWithdrawRespVO;
import cn.iocoder.yudao.module.pay.controller.admin.walletwithdraw.vo.PayWalletWithdrawCheckReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.walletwithdraw.vo.PayWalletWithdrawPageReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.walletwithdraw.vo.PayWalletWithdrawSaveReqVO;
import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.walletwithdraw.PayWalletWithdrawDO;
import cn.iocoder.yudao.module.pay.dal.mysql.walletwithdraw.PayWalletWithdrawMapper;
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
import cn.iocoder.yudao.module.pay.service.wallet.PayWalletService;
import cn.iocoder.yudao.module.trade.api.tradedelivery.TradeOrderDeliveryApi;
import cn.iocoder.yudao.module.trade.api.tradedelivery.dto.TradeOrderDeliveryDTO;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;

/**
 * 钱包提现 Service 实现类
 *
 * @author FFFF
 */
@Service
@Validated
public class PayWalletWithdrawServiceImpl implements PayWalletWithdrawService {

    @Resource
    private PayWalletWithdrawMapper walletWithdrawMapper;
    @Autowired
    private PayWalletService payWalletService;
    @Resource
    private PayOrderService payOrderService;
    @Resource
    private TradeOrderDeliveryApi tradeOrderDeliveryApi;
    @Resource
    private PickupInfoApi pickupInfoApi;
    @Resource
    private MemberUserApi memberUserApi;

    @Override
    @Transactional
    public Long createWalletWithdraw(PayWalletWithdrawSaveReqVO createReqVO) {
        // 插入
        PayWalletWithdrawDO walletWithdraw = BeanUtils.toBean(createReqVO, PayWalletWithdrawDO.class);
        // 校验钱包与用户
        PayWalletDO wallet = payWalletService.getWallet(createReqVO.getWalletId());
        if (wallet == null) {
            throw exception(WALLET_NOT_FOUND);
        }
        // 校验提现金额
        if (createReqVO.getPrice().compareTo(wallet.getBalance().subtract(wallet.getFreezePrice())) > 0) {
            throw exception(WALLET_BALANCE_NOT_ENOUGH);
        }
        // 冻结金额
        payWalletService.freezePrice(wallet.getId(), createReqVO.getPrice(), PayWalletBizTypeEnum.WITHDRAW);
        walletWithdraw.setUserId(getLoginUserId());
        walletWithdrawMapper.insert(walletWithdraw);
        // 创建提料物流单
        if (!PayWalletTypeEnum.RMB.getType().equals(wallet.getWalletType())) {
            tradeOrderDeliveryApi.createPickUpDelivery(wallet.getUserId(), walletWithdraw.getId(), createReqVO.getDeliveryType(),
                    createReqVO.getPickUpStoreId(), createReqVO.getAddressId(),createReqVO.getPickupInfoId());
        }
        // 返回
        return walletWithdraw.getId();
    }

    @Override
    @Transactional
    public Boolean cancelWalletWithdraw(Long id) {
        // 校验存在
        PayWalletWithdrawDO walletWithdraw = walletWithdrawMapper.selectById(id);
        if (walletWithdraw == null) {
            throw exception(WALLET_WITHDRAW_NOT_EXISTS);
        }
        // 校验状态
        if (!WithdrawStatusEnum.AUDITING.getStatus().equals(walletWithdraw.getStatus())) {
            throw exception(new ErrorCode(99999999,"提现不是待审核状态"));
        }
        // 解冻金额
//        payWalletService.unfreezePrice(walletWithdraw.getWalletId(), walletWithdraw.getPrice()),
//                PayWalletBizTypeEnum.WITHDRAW_CANCEL);
        payWalletService.unfreezePrice(walletWithdraw.getWalletId(), walletWithdraw.getPrice());
        // 更新状态
        walletWithdraw.setStatus(WithdrawStatusEnum.WITHDRAW_CANCEL.getStatus());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void checkWalletWithdraw(PayWalletWithdrawCheckReqVO checkReqVO) {
        // 校验存在
        PayWalletWithdrawDO walletWithdrawDO = walletWithdrawMapper.selectById(checkReqVO.getId());
        if (walletWithdrawDO == null) {
            throw exception(WALLET_WITHDRAW_NOT_EXISTS);
        }
        if (checkReqVO.getConfirm() == null) {
            throw exception(new ErrorCode(99999999, "是否通过不能为空"));
        }
        // 更新
        PayWalletWithdrawDO updateObj = BeanUtils.toBean(checkReqVO, PayWalletWithdrawDO.class);
        if (checkReqVO.getConfirm()) {
            if (checkReqVO.getPayPicUrl() == null || checkReqVO.getPayPicUrl().size() == 0) {
                throw exception(new ErrorCode(99999999,"打款截图不能为空"));
            }
            if (checkReqVO.getPayPrice() == null || checkReqVO.getPayPrice().compareTo(walletWithdrawDO.getPrice()) != 0) {
                throw exception(new ErrorCode(99999999,"打款金额错误"));
            }
            updateObj.setStatus(WithdrawStatusEnum.AUDIT_SUCCESS.getStatus())
                    .setPayPrice(checkReqVO.getPayPrice())
                    .setPayPicUrl(checkReqVO.getPayPicUrl())
                    .setAuditReason(checkReqVO.getAudiReason())
                    .setAdminId(getLoginUserId())
                    .setAuditTime(LocalDateTime.now())
                    .setPayTime(LocalDateTime.now());
        } else {
            updateObj.setStatus(WithdrawStatusEnum.AUDIT_FAIL.getStatus());
        }
        if (WithdrawTypeEnum.PAYMENT.getType().equals(walletWithdrawDO.getType()) && checkReqVO.getConfirm()) {
            updateObj.setStatus(WithdrawStatusEnum.PAY_SUCCESS.getStatus());
            // 支付单进行支付
            payOrderService.createSubmitByPayOrder(Long.parseLong(walletWithdrawDO.getBizNo()), checkReqVO.getPayPicUrl());
        } else {
           // 对钱包冻结金额进行 解冻
           payWalletService.unfreezePrice(walletWithdrawDO.getWalletId(), checkReqVO.getPayPrice());
           payWalletService.reduceWalletBalance(walletWithdrawDO.getWalletId(),walletWithdrawDO.getId(), PayWalletBizTypeEnum.WITHDRAW,checkReqVO.getPayPrice(), "");
        }

        walletWithdrawMapper.updateById(updateObj);
    }

    @Override
    public void createWithDrawBySystem(BigDecimal price, Long userId, String orderNo, String name, String bankId, String bankName, String bankAddress) {
        PayWalletWithdrawDO walletWithdrawDO = new PayWalletWithdrawDO();
        walletWithdrawDO.setUserId(userId);
        walletWithdrawDO.setPrice(price);
        walletWithdrawDO.setType(WithdrawTypeEnum.PAYMENT.getType());    //打款单
        walletWithdrawDO.setName(name);
        walletWithdrawDO.setAccountNo(bankId);
        walletWithdrawDO.setBankName(bankName);
        walletWithdrawDO.setBankAddress(bankAddress);
        walletWithdrawDO.setStatus(WithdrawStatusEnum.WAIT_PAY.getStatus()); //待打款
        walletWithdrawDO.setBizNo(orderNo);
        walletWithdrawMapper.insert(walletWithdrawDO);
    }

    @Override
    public PageResult<PayWalletMetalWithdrawRespVO> getWalletWithdrawPickupPage(PayWalletWithdrawPageReqVO pageReqVO) {
        PageResult<PayWalletWithdrawDO> page = getWalletWithdrawPage(pageReqVO);
        List<PayWalletMetalWithdrawRespVO> list = new ArrayList<>(page.getList().size());
        for (PayWalletWithdrawDO withDraw : page.getList()) {
            TradeOrderDeliveryDTO deliveryDTO = tradeOrderDeliveryApi.queryByWithdrawId(withDraw.getId());
            PickupInfoDTO pickupInfo = pickupInfoApi.getPickupInfo(deliveryDTO.getPickupInfoId());
            String name = memberUserApi.getUserName(withDraw.getUserId());
            list.add(BeanUtils.toBean(withDraw, PayWalletMetalWithdrawRespVO.class)
                    .setUserName(name)
                    .setDeliveryInfo(deliveryDTO)
                    .setPickupInfo(pickupInfo));
        }
        return new PageResult<>(list, page.getTotal());
    }

    @Override
    public void updateWalletWithdraw(PayWalletWithdrawSaveReqVO updateReqVO) {
        // 校验存在
        validateWalletWithdrawExists(updateReqVO.getId());
        // 更新
        PayWalletWithdrawDO updateObj = BeanUtils.toBean(updateReqVO, PayWalletWithdrawDO.class);
        walletWithdrawMapper.updateById(updateObj);
    }

    @Override
    public void deleteWalletWithdraw(Long id) {
        // 校验存在
        validateWalletWithdrawExists(id);
        // 删除
        walletWithdrawMapper.deleteById(id);
    }

    private void validateWalletWithdrawExists(Long id) {
        if (walletWithdrawMapper.selectById(id) == null) {
            throw exception(WALLET_WITHDRAW_NOT_EXISTS);
        }
    }

    @Override
    public PayWalletWithdrawDO getWalletWithdraw(Long id) {
        return walletWithdrawMapper.selectById(id);
    }

    @Override
    public PageResult<PayWalletWithdrawDO> getWalletWithdrawPage(PayWalletWithdrawPageReqVO pageReqVO) {
        return walletWithdrawMapper.selectPage(pageReqVO);
    }



}